package org.jsola.hr.service.impl;

import com.google.common.collect.Lists;
import org.jsola.admin.vo.SiteVO;
import org.jsola.core.Page;
import org.jsola.exception.ParamException;
import org.jsola.hr.common.ExampleKit;
import org.jsola.hr.constant.GysGroupType;
import org.jsola.hr.constant.HrConstants;
import org.jsola.hr.dao.IGysGroupDAO;
import org.jsola.hr.dto.GysGroupAddDTO;
import org.jsola.hr.dto.GysGroupUpdateDTO;
import org.jsola.hr.entity.GysGroupDO;
import org.jsola.hr.entity.GysInfoDO;
import org.jsola.hr.provider.IAdminProviderService;
import org.jsola.hr.query.GysGroupQuery;
import org.jsola.hr.service.IGysGroupService;
import org.jsola.hr.service.IGysInfoService;
import org.jsola.hr.vo.GysGroupListVO;
import org.jsola.hr.vo.GysGroupVO;
import org.jsola.user.core.TokenUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import tk.mybatis.mapper.entity.Example;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 甲方端供应商分组
 *
 * @author zhr
 */
@Service("hrGysGroupServiceImpl")
public class GysGroupServiceImpl implements IGysGroupService {

    @Autowired
    private IGysGroupDAO gysGroupDAO;

    @Autowired
    private IGysInfoService gysInfoService;

    @Autowired
    private IAdminProviderService adminProviderService;

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public GysGroupVO save(GysGroupAddDTO gysGroupAddDTO, TokenUser tokenUser) {
        // 校验分组名称
        checkGroupName(gysGroupAddDTO.getName(), null, tokenUser);
        // 转DO
        GysGroupDO gysGroupDO = gysGroupAddDTO.to(GysGroupDO.class);
        // 保存
        gysGroupDO = save(gysGroupDO, tokenUser.getSiteId(), tokenUser.getUserId());
        return gysGroupDO.to(GysGroupVO.class);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int update(GysGroupUpdateDTO gysGroupUpdateDTO, TokenUser tokenUser) {
        // 校验分组名称
        checkGroupName(gysGroupUpdateDTO.getName(), gysGroupUpdateDTO.getId(), tokenUser);
        //转DO
        GysGroupDO gysGroupDO = gysGroupUpdateDTO.to(GysGroupDO.class);
        //根据主键更新，只更新非null值
        return updateByIdSelective(gysGroupDO, tokenUser.getSiteId(), tokenUser.getUserId());
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int deleteByIds(TokenUser tokenUser, String... gysGroupIds) {
        for (String gysGroupId : gysGroupIds) {
            List<String> idList = selectByParentIdList(Collections.singletonList(gysGroupId), tokenUser.getSiteId());
            // 查询准备删除的分组下还有没有供应商
            List<GysInfoDO> gysInfoList = gysInfoService
                    .selectGysByGroupIdList(idList, tokenUser);
            if (!CollectionUtils.isEmpty(gysInfoList)) {
                throw new ParamException("分组或子分组下存在供应商");
            }
        }
        return logicalDeleteByIds(tokenUser.getSiteId(), tokenUser.getUserId(), (Object[]) gysGroupIds);
    }


    @Override
    public GysGroupVO selectById(String gysGroupId, String siteId) {
        GysGroupDO gysGroupDO = selectDOById(gysGroupId, siteId);
        if (gysGroupDO == null) {
            return null;
        }
        return gysGroupDO.to(GysGroupVO.class);
    }

    @Override
    public List<GysGroupListVO> select(GysGroupQuery gysGroupQuery, String siteId) {
        List<GysGroupDO> gysGroupDOList = selectDO(gysGroupQuery, siteId);
        if (CollectionUtils.isEmpty(gysGroupDOList)) {
            return gysGroupDOList == null ? null : new ArrayList<>();
        }
        return gysGroupDOList.stream()
                .map(gysGroupDO -> gysGroupDO.to(GysGroupListVO.class))
                .collect(Collectors.toList());
    }

    @Override
    public int selectCount(GysGroupQuery gysGroupQuery, String siteId) {
        Example example = buildExample(gysGroupQuery, siteId);
        return gysGroupDAO.selectCountByExample(example);
    }

    @Override
    public Page<GysGroupListVO> selectPage(GysGroupQuery gysGroupQuery, String siteId) {
        Example example = buildExample(gysGroupQuery, siteId);
        Page<GysGroupDO> page = gysGroupDAO.selectPageByExample(example,
                gysGroupQuery.getPageNo(),
                gysGroupQuery.getPageSize());

        return page.to(GysGroupListVO.class);
    }

    @Override
    public GysGroupDO selectDOById(String gysGroupId, String siteId) {
        return listById(gysGroupId, siteId);
    }

    @Override
    public List<GysGroupDO> selectDO(GysGroupQuery gysGroupQuery, String siteId) {
        Example example = buildExample(gysGroupQuery, siteId);
        return gysGroupDAO.selectByExample(example);
    }

    @Override
    public List<GysGroupVO> selectGroupByType(String groupType, String siteId) {
        Example example = new Example(GysGroupDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId)
                .andEqualTo("groupType", groupType);
        List<GysGroupDO> gysGroupList = gysGroupDAO.selectByExample(example);
        if (CollectionUtils.isEmpty(gysGroupList)) {
            return new ArrayList<>();
        } else {
            return gysGroupList.stream()
                    .map(group -> group.to(GysGroupVO.class))
                    .collect(Collectors.toList());
        }
    }

    @Override
    public List<GysGroupVO> selectGroupTree(GysGroupQuery gysGroupQuery, TokenUser tokenUser) {
        // 先查询租户级分组有没有创建,没有先创建租户级供应商分组
        List<GysGroupVO> siteGroupList =
                this.selectGroupByType(GysGroupType.SITE_GROUP.getValue(), tokenUser.getSiteId());
        if (CollectionUtils.isEmpty(siteGroupList)) {
            this.initSiteGroup(tokenUser);
        }
        // 如果有搜索条件,直接平铺展开 (也算是两级,第一级是租户级别分组,第二级全部平铺)
        if (!StringUtils.isEmpty(gysGroupQuery.getGroupName())) {
            List<GysGroupDO> gysGroupList = selectGroupByName(gysGroupQuery.getGroupName(), tokenUser.getSiteId());
            // 数组中只有一个(租户级别分组)
            List<GysGroupVO> result =
                    this.selectGroupByType(GysGroupType.SITE_GROUP.getValue(), tokenUser.getSiteId());
            GysGroupVO siteGroup = result.get(0);
            List<String> childGroupIdList = this.selectByParentIdList
                    (Collections.singletonList(siteGroup.getId()), tokenUser.getSiteId());
            if (!CollectionUtils.isEmpty(gysGroupList)) {
                List<GysGroupVO> gysGroupListVO = gysGroupList.stream()
                        .map(group -> group.to(GysGroupVO.class)).collect(Collectors.toList());
                for (GysGroupVO gysGroup : gysGroupListVO) {
                    int groupGysCount = gysInfoService.selectGysByGroupIdList
                            (Collections.singletonList(gysGroup.getId()), tokenUser).size();
                    gysGroup.setGysCount(groupGysCount);
                }
                siteGroup.setChildList(gysGroupListVO);
                siteGroup.setGysCount(gysInfoService.selectGysByGroupIdList(childGroupIdList, tokenUser).size());
            }
            return result;
        } else {
            List<GysGroupVO> gysGroupList = gysGroupDAO.selectGroupTree(tokenUser.getSiteId());
            return buildGroupTree(gysGroupList, "0", tokenUser);
        }
    }

    @Override
    public List<String> selectByParentIdList(List<String> parentIdList, String siteId) {
        List<String> iteratorList = new ArrayList<>(parentIdList);
        for (String parentId : parentIdList) {
            Example example = new Example(GysGroupDO.class);
            example.and()
                    .andEqualTo("parentId", parentId)
                    .andEqualTo("valid", true)
                    .andEqualTo("siteId", siteId);
            List<GysGroupDO> contactsGroupList = gysGroupDAO.selectByExample(example);
            if (CollectionUtils.isEmpty(contactsGroupList)) {
                continue;
            }
            List<String> childrenDepIdList =
                    contactsGroupList.stream().map(GysGroupDO::getId).collect(Collectors.toList());
            iteratorList.addAll(selectByParentIdList(childrenDepIdList, siteId));
        }
        return iteratorList;
    }

    @Override
    public List<GysGroupDO> selectGroupByName(String groupName, String siteId) {
        Example example = new Example(GysGroupDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId)
                .andLike("name", "%" + groupName + "%");
        return gysGroupDAO.selectByExample(example);
    }

    /**
     * 初始化租户供应商分组
     */
    private void initSiteGroup(TokenUser tokenUser) {
        // 保存租户级别分组
        SiteVO site = adminProviderService.selectSiteById(tokenUser.getSiteId(), tokenUser);
        GysGroupAddDTO siteGroup = new GysGroupAddDTO();
        siteGroup.setName(site.getName());
        siteGroup.setGroupType(GysGroupType.SITE_GROUP.getValue());
        siteGroup.setParentId("0");
        siteGroup.setSort(0L);
        siteGroup.setLevel(1);
        GysGroupVO result = save(siteGroup, tokenUser);
        // 保存默认分组
        GysGroupAddDTO defaultGroup = new GysGroupAddDTO();
        defaultGroup.setName("默认分组");
        defaultGroup.setGroupType(GysGroupType.ORDINARY_GROUP.getValue());
        defaultGroup.setParentId(result.getId());
        defaultGroup.setSort(1L);
        defaultGroup.setLevel(2);
        save(defaultGroup, tokenUser);
    }

    /**
     * 构建供应商分组树
     */
    private List<GysGroupVO> buildGroupTree(List<GysGroupVO> gysGroupList, String parentId, TokenUser tokenUser) {
        List<GysGroupVO> resultList = Lists.newArrayList();
        for (GysGroupVO gysGroup : gysGroupList) {
            if (gysGroup.getParentId().equals(parentId)) {
                gysGroup.setHasChild(Boolean.TRUE.equals(gysGroup.getHasChild()));
                // 先查询这个部门的子部门
                List<String> childGroupIdList = this.selectByParentIdList
                        (Collections.singletonList(gysGroup.getId()), tokenUser.getSiteId());
                // 查询部门下的员工数
                gysGroup.setGysCount(gysInfoService.selectGysByGroupIdList(childGroupIdList, tokenUser).size());
                resultList.add(gysGroup);
                if (gysGroup.getHasChild()) {
                    //将父id为此组织的放到子组织列表
                    gysGroup.setChildList(buildGroupTree(gysGroupList, gysGroup.getId(), tokenUser));
                }
            }
        }
        return resultList;
    }

    /**
     * 校验分组名称
     */
    private void checkGroupName(String groupName, String groupId, TokenUser tokenUser) {
        Example example = new Example(GysGroupDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("name", groupName)
                .andEqualTo("siteId", tokenUser.getSiteId());
        List<GysGroupDO> gysGroupList = gysGroupDAO.selectByExample(example);
        // 如果有Id传入说明是 update 方法校验,这个时候需要把自己给过滤出去
        if (!StringUtils.isEmpty(groupId)) {
            gysGroupList = gysGroupList.stream()
                    .filter(gysGroup -> !groupId.equals(gysGroup.getId())).collect(Collectors.toList());
        }
        if (!CollectionUtils.isEmpty(gysGroupList)) {
            throw new ParamException("供应商分组名称重复");
        }
    }

    /**
     * 根据查询参数，构建example
     *
     * @param gysGroupQuery 查询参数
     * @param siteId        所属站点id
     * @return example
     */
    private Example buildExample(GysGroupQuery gysGroupQuery, String siteId) {
        Example example = new Example(GysGroupDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId);
        if (gysGroupQuery.getParentId() != null) {
            example.and().andEqualTo("parentId", gysGroupQuery.getParentId());
        }
        if (gysGroupQuery.getLevel() != null) {
            example.and().andEqualTo("level", gysGroupQuery.getLevel());
        }
        // 排序
        ExampleKit.setExampleOrder(example, gysGroupQuery.getOrders());
        return example;
    }
}




